<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="pragma" content="no-cache" />

    <link rel="stylesheet" type="text/css" href="/assets/bootstrap-3.3.7-dist/css/bootstrap.min.css" />
  </head>
  <body style="background-color: #666; font-size: 1.6em; ">

    <div id="panel_login" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; ">
      <span style="font-size: 1.2em; font-weight: bold; ">裁判系统</span><br /><hr />
      登录为: <select id="text_login_type">
        <option value="BEGIN" selected>发令员</option>
        <option value="TIMER">裁判: 计时员</option>
        <option value="SEQUENCER">裁判: 计次员</option>
        <option value="RECTIFIER">成绩校正员</option>
      </select><br /><br />
      <table style="width: 100%; ">
        <tr><td>你的ID: </td><td><input id="text_login_identifier" /></td></tr>
        <tr><td>统一密码: </td><td><input type="password" id="text_login_password" /></td></tr>
      </table>

      <button id="btn_login" style="btn btn-primary btn-sm">登录</button>
    </div>

    <div id="panel_wait" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; ">
      <span style="font-size: 1.2em; font-weight: bold; ">正在获取网络信息</span>
      collecting data from remote server... <hr />
    </div>

    <div id="panel_begin_control" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; ">
      <span style="font-size: 1.2em; font-weight: bold; ">可以发令</span>
      ready to make a begin signal! <hr />
      <button onclick='ws.send("control;begin;" + current_latency);' class="btn btn-lg btn-danger">【 发 令 起 跑 】</button>
    </div>
    <div id="panel_begin_done" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; ">
      <span style="font-size: 1.2em; font-weight: bold; ">发令成功</span>
      signal emitted! <hr />
    </div>

    <div id="panel_not_available" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; ">
      <span style="font-size: 1.2em; font-weight: bold; ">比赛不可用已经在进行中了，请不要退出等待下一场。</span>
      contest not available or already in progress! 
    </div>

    <div id="panel_select_track" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; ">
      <span style="font-size: 1.2em; font-weight: bold; ">选择裁判赛道</span>
      select track. 
      <div id="div_track_selector"></div>
    </div>

    <!-- TIMER AND SEQUENCER-->

    <div id="panel_general_stopwatch" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; width: 480px; height: 120px; ">
      <span style="width: 100%; height: 100% ; font-size: 2.5em; "><span id="indicator_stopwatch" style="font-weight: bold; "></span>秒</span>
    </div><br />
    <div id="panel_timer_control" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; width: 480px; height: 200px; ">
      <button onclick="send_timer_finish(); " class="btn btn-lg btn-warning" style="width: 100%; height: 100% ; ">【 停 表 】</button>
    </div>
    <div id="panel_sequencer_control" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; ">
      <span style="font-size: 1.2em; "><span id="indicator_stopwatch" style="font-weight: bold; "></span>秒</span>
    </div>
    <div id="panel_general_okay" class="panel-session" style="margin: 32px; background-color: #cbe; padding: 16px; border-radius: 12px; display: none; ">
      <span style="font-size: 1.2em; font-weight: bold; ">完成! </span>complete! 
    </div>

    <!-- Results -->
    <div style="margin: 48px; background-color: #888; border-radius: 6px; padding: 4px; ">状态:<span id="message"></span></div>
    <div id="panel_latency" style="font-size: 0.8em; margin: 32px; background-color: #888; padding: 4px; border-radius: 12px; display: none; ">
      <div id="indicator_ping" style="display: inline-block; width: 24px; height: 24px; margin: 8px; "></div>平均延迟: <span id="display_latency"></span>毫秒 (<span id="display_latency_update_timestamp"></span>)
    </div>

    <script type="text/javascript" src="/assets/jquery-3.4.1.min.js"></script>
    <script type="text/javascript" src="/assets/base64.js"></script>
    <script type="text/javascript" src="/assets/contest-deserializer.js"></script>
    <script type="text/javascript" src="/assets/track-selector.js"></script>

    <script>
      var connected = false; 
      var user_type = null;
      var current_contest = null; // access state within here
      var current_contest_available = false; // 是否参与了这场比赛的裁判? 
      var track_selected_state = false;
      var track_selected = null; // 选择了的赛道, string
      var track_selected_server_confirmed = false;

      var last_ping_id = 0;
      var last_ping_timestamp = 0;
      var total_latency = 0; // in milliseconds
      var total_pings = 0; // how many times
      var current_latency = 0;

      var track_begin_timestamp = -1;

      var timer_is_stopped = false;
      var timer_server_confirmed = -1;

      function show_login() {
        $("#panel_login").css("display", "inline-block");
        hide_all_session_panels();
      }
      function hide_all_session_panels() {
        $(".panel-session").css("display", "none");
      }
      function showMessage(text) {
        $("#message").html(text);
      }
      function send_ping() {
        last_ping_timestamp = +new Date();
        if(connected) {
          ws.send("ping;" + last_ping_id + ";" + last_ping_timestamp);
        }
      }

      function resetAllState() {
        current_contest = null;
        current_contest_available = false;
        track_selected_state = false;
        track_selected = null;
        track_selected_server_confirmed = false;
        track_begin_timestamp = -1;
        timer_is_stopped = false;
        timer_server_confirmed = -1;
      }
      function show(selector) {
        $(selector).css("display", "inline-block");
      }
      function hide(selector) {
        $(selector).css("display", "none");
      }
      function select_track(track_local_index) {
        if(current_contest != null && current_contest_available) {
          if(track_selected_state && track_selected_server_confirmed) {
            showMessage("赛道已经选择! "); 
            return;
          }
          track_selected = current_contest.tracks[track_local_index].name;
          track_selected_state = true;

          ws.send("track;" + track_selected);
          // show designated panel
          hide_all_session_panels();
          show("#panel_wait");
          showMessage("等待服务器确认... ");
        } else {
          showMessage("无效状态! error");
        }
      }
      function update_stopwatch() {
        if(!connected || !current_contest_available) return;
        if(timer_is_stopped) {
          $("#indicator_stopwatch").html((timer_server_confirmed) / 1000);
          return;
        }
        $("#indicator_stopwatch").html((new Date() - track_begin_timestamp) / 1000);
        setTimeout(update_stopwatch, 50);
      }
      // invoked when timer clicked stop button
      function send_timer_finish() {
        if(!track_selected_state || !track_selected_server_confirmed || !current_contest_available || current_contest == null) return;
        ws.send("timer;stop;" + current_latency);
        showMessage("已经发送停表信号，等待服务器确认... ");
      }

      // onData() start
      function onData(msg) {
        var params = msg.data.split(";");

        // authentication
        if(params[0] == "auth") {
          if(params[1] == "request") {
            // request
            show_login();
            return;
          }
          if(params[1] == "success") {
            hide("#panel_login");
            show("#panel_wait");
            show("#panel_latency");
            showMessage("登陆成功! ");
            ws.send("contest;get");
            send_ping();
            return;
          }
          if(params[1] == "fail") {
            showMessage("登陆失败! " + params[2]);
            return;
          }
          return;
        }
        if(params[0] == "message") {
          showMessage(params[1]);
        }
        // pong start
        if(params[0] == "pong") {
          var received_ping_id = parseInt(params[1]);
          if(received_ping_id == last_ping_id) {
            if(total_latency > 50000) {
              total_latency = 0;
              total_pings = 0;
            }
            total_latency += (new Date() - last_ping_timestamp) / 2;
            total_pings++;
            if(total_pings % 2 == 0) {
              $("#indicator_ping").css("background-color", "#2E2");
            } else {
              $("#indicator_ping").css("background-color", "#222");
            }
            current_latency = Math.round(total_latency / total_pings);
            $("#display_latency").html(current_latency);
            $("#display_latency_update_timestamp").html(+new Date());

            setTimeout(send_ping, 1000);
          }
          last_ping_id++;
        }
        // pong end
        // contest start
        if(params[0] == "contest") {
          if(params[1] == "state") {
            if(params[2] == "yes") {
              showMessage("竞赛状态可用，等待接收比赛信息... ");
              current_contest_available = true;
            } else {
              current_contest_available = false;
              hide_all_session_panels();
              $("#panel_not_available").css("display", "inline-block");
            }
            return;
          }
          if(params[1] == "data") {
            current_contest = deserialize_contest(params[2]);
            showMessage("接收到比赛数据 [" + current_contest.name + "]. ");

            // 分赛道裁判
            if(user_type == "SEQUENCER" || user_type == "TIMER") {
              if(current_contest_available && !track_selected_state) {
                // composite track selector
                hide_all_session_panels();
                $("#div_track_selector").html(create_track_selector_buttons(current_contest));
                show("#panel_select_track");
              }
            }
            return;
          }
          return;
        }
        // contest end
        // state start
        if(params[0] == "state") {
          if(current_contest == null) return;
          var previous_state = current_contest.state;
          current_contest.state = params[1];
          showMessage("比赛状态更新: " + previous_state + " > " + current_contest.state);
          if(params[1] == "WAITING" && previous_state != "WAITING") {
            if(user_type == "SEQUENCER" || user_type == "TIMER") {
              if(!track_selected_state || !current_contest_available || track_selected == null || !track_selected_server_confirmed) {
                hide_all_session_panels();
                show("#panel_not_available");
                showMessage("比赛状态已经改变, 您没有及时选择赛道信息或没有权限! ");
                return;
              }
            }
            if(user_type == "BEGIN" && current_contest_available) {
              hide_all_session_panels();
              show("#panel_begin_control");
              showMessage("可以发令起跑! ready to go. ");
              return;
            }
            return;
          }
          if(previous_state == "WAITING" && params[1] == "STANDBY" && current_contest_available) {
            if((user_type == "TIMER" || user_type == "SEQUENCER") && (!track_selected_state || track_selected == null || !track_selected_server_confirmed)) {
              // not selected?
              hide_all_session_panels();
              show("#panel_select_track");
              return;
            }
            if(user_type == "BEGIN") {
              hide_all_session_panels();
              show("#panel_wait");
            }
          }
          if(params[1] == "TRACKING" && current_contest_available) {
            track_begin_timestamp = +new Date();
            if(user_type == "BEGIN") {
              hide_all_session_panels();
              show("#panel_begin_done");
            }
            if((user_type == "TIMER" || user_type == "SEQUENCER") && track_selected_state && track_selected_server_confirmed) {
              hide_all_session_panels();
              show("#panel_general_stopwatch");
              setTimeout(update_stopwatch, 50);
              if(user_type == "TIMER") {
                show("#panel_timer_control");
              } else if (user_type == "SEQUENCER") {
                show("#panel_timer_control");
              }
              return;
            }
          }
          return;
        }
        // state end
        // track start
        if(params[0] == "track") {
          if(params[1] == "confirmed" && track_selected_state == true && current_contest_available) {
            showMessage("裁判资格已注册并确认! " + user_type + " 赛道: " + track_selected);
            track_selected_server_confirmed = true;
          } else {
            showMessage(params[2]);
          }
          return;
        }
        // track end
        // timer start
        if(params[0] == "timer" && current_contest_available && track_selected_state && track_selected_server_confirmed) {
          if(params[1] == "confirmed") {
            timer_server_confirmed = parseInt(params[2]);
            hide_all_session_panels();
            timer_is_stopped = true;
            show("#panel_general_stopwatch");
            show("#panel_general_okay");
          }
        }
        // timer end
        // reset start
        if(params[0] == "reset") {
          if(user_type == "BEGIN" || user_type == "TIMER") {
            resetAllState();
            hide_all_session_panels();
             show("#panel_wait");
            showMessage("服务器发出重置信号，等待数据中... ");
            ws.send("contest;get");
          }
        }
        // reset end
        return;
      }
      // onData() end

      var ws = new WebSocket('ws://' + document.location.host + '/connect');
      showMessage('连接中...');
      ws.onopen = function() { showMessage('连接成功!'); connected = true;};
      ws.onclose = function() { showMessage('连接断开, 请刷新本页面重试! '); connected = false; show_login(); hide("#panel_latency"); };
      ws.onmessage = onData;

      // login button
      $("#btn_login").click(function(e) {
        if(!connected) {
          showMessage("还未连接到服务器，无法登陆! ");
          return;
        }
        if($("#text_login_type").val().trim() == "") {
          showMessage("请输入完整密码! ");
          return;
        }
        var base64 = new Base64();
        var uid_encoded = base64.encode($("#text_login_identifier").val());
        var pwd_encoded = base64.encode($("#text_login_password").val());
        user_type = $("#text_login_type").val(); // global
        ws.send("auth;" + user_type + ";"+ uid_encoded + ";" + pwd_encoded);
      });
    </script>
  </body>
</html>
